package com.thams.dao;

import javax.naming.NamingException;
import javax.sql.DataSource;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.jndi.JndiLocatorSupport;

/**
 * @author: luyu
 * @date: Aug 6, 2008
 *  
 * @Function: 自定义DataSourceFactoryBean 实现 FactoryBean, {@link InitializingBean}  
 * 为了方便jndi配置 和开发是灵活切换.更改config/jdbc.properties的jdbc.IS_JNDI=true为false就是使用传统datasource获得连接
 */
public class DataSourceFactoryBean implements FactoryBean, InitializingBean {
	private Logger log = Logger.getLogger(DataSourceFactoryBean.class);
	/** 缓存数据源对象 */
	private DataSource dataSource;
	/** 是否jndi数据源 */
	private boolean jndi;
	/** 数据源的名字（如果是jndi数据源） */
	private String jndiName;
	/** jdbc驱动类(非jndi的情况) */
	private String driverClassName;
	/** 数据库的url(非jndi的情况) */
	private String url;
	/** 用户名(非jndi的情况) */
	private String username;
	/** 密码(非jndi的情况) */
	private String password;

	public void afterPropertiesSet() throws Exception {
		if (this.isJndi()) {
			if (!org.springframework.util.StringUtils.hasText(this.jndiName)) {
				throw new IllegalArgumentException("jndiName is required");
			}
		} else {
			if (!org.springframework.util.StringUtils
					.hasText(this.driverClassName)) {
				throw new IllegalArgumentException(
						"driverClassName is required");
			}
			if (!org.springframework.util.StringUtils.hasText(this.url)) {
				throw new IllegalArgumentException("url is required");
			}
			if (!org.springframework.util.StringUtils.hasText(this.username)) {
				throw new IllegalArgumentException("username is required");
			}
			if (!org.springframework.util.StringUtils.hasText(this.password)) {
				throw new IllegalArgumentException("password is required");
			}
		}
		// 在初始化时就创建数据源
		this.createDataSource();
	}

	public Object getObject() throws Exception {
		DataSource ds = this.createDataSource();
		return ds;
	}

	public Class getObjectType() {
		return javax.sql.DataSource.class;
	}

	public boolean isSingleton() {
		return true;
	}

	protected DataSource createDataSource() {
		DataSource ds = this.dataSource;
		if (ds == null) {
			try {
				if (this.isJndi()) {
					ds = new JndiDataSourceSupport().lookupDataSource(this.jndiName);
					//System.out.println("JNDI NAME: "+this.jndiName+" is started!");
				} else {
					ds = new DriverManagerDataSource(driverClassName, url,
							username, password);
				}
			} catch (Throwable err) {
				log.error(err.getMessage());
			}
		}
		this.dataSource = ds;
		return ds;
	}

	private class JndiDataSourceSupport extends JndiLocatorSupport {
		public DataSource lookupDataSource(String jndiName) {
			try {
				return (DataSource) super.lookup(jndiName, getObjectType());
			} catch (NamingException e) {
				log.error("数据源连接出错！请查看您的jdbc或者jndi配置！信息："+e.getMessage());
				return null;
			}
		}
	}

	/** *************set get ********* */

	public DataSource getDataSource() {
		return dataSource;
	}

	public void setDataSource(DataSource dataSource) {
		this.dataSource = dataSource;
	}

	public boolean isJndi() {
		return jndi;
	}

	public void setJndi(boolean jndi) {
		this.jndi = jndi;
	}

	public String getJndiName() {
		return jndiName;
	}

	public void setJndiName(String jndiName) {
		this.jndiName = jndiName;
	}

	public String getDriverClassName() {
		return driverClassName;
	}

	public void setDriverClassName(String driverClassName) {
		this.driverClassName = driverClassName;
	}

	public String getUrl() {
		return url;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

}
